package net.mfjassociates.financial.server.domain;

import static java.lang.Math.floor;
import static java.lang.Math.log10;
import static java.lang.Math.pow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;

import net.mfjassociates.financial.shared.domain.Ids;



public final class DocumentId {
	private static DocumentId instance;
	private static final int MAX_RANDOM=10;
	private static final int START_RANDOM=(int) pow(10, floor(1+log10((MAX_RANDOM-1l)*10))-1);
	private Ids ids;
	private Logger logger = Logger.getLogger(getClass());

	public static void main(String[] args) {
		System.out.println("new hash="+generateNewHash());
	}
	private DocumentId() {
		/* temporary for debugging only */
		List<Ids> ii=Ids.findIdsEntries(0,1000);
		System.out.println("list size="+ii.size());
		for (Iterator iterator = ii.iterator(); iterator.hasNext();) {
			Ids ids = (Ids) iterator.next();
			ids.remove();
			ids.flush();
		}
		ii=Ids.findIdsEntries(0,1000);
		System.out.println("list size after="+ii.size());
		/* end of debugging */
		// Initialisation
		Ids i = Ids.findIdsByRowid(0);
		if (i==null) {
			i=new Ids();
			i.setRowid(0); // rowid = 0 is the only row in entity Ids that contains the random parameters.
			initializeIds(i);
			i.persist();
		} else { // Ids rowid 0 existed
		}
		this.ids=i;
	}
	
	private void initializeIds(Ids initializeids) {
		logger.info("Invoking initializeIds");
		ArrayList<Integer> li=new ArrayList<Integer>(MAX_RANDOM);
		for (int i = 0; i < MAX_RANDOM; i++) {
			li.add(i);
		}
		Collections.shuffle(li);
		for (int i = 0; i < MAX_RANDOM; i++) {
			Ids ids=Ids.findIdsByRowid(i+1);
			if (ids==null) {
				ids=new Ids();
				ids.persist();
			}
			ids.setRowid(1+i);
			ids.setRandomValue(li.get(i));
			ids.flush();
		}
		initializeids.setRandomValue(1); // current rowid on rowid=0, otherwise the next value
		initializeids.setHash(generateNewHash());
		initializeids.flush();
	}

	public static DocumentId getInstance() {
		if (instance == null)
			instance = new DocumentId();
		return instance;
	}

	public Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
		// that'll teach 'em
	}
	public synchronized String getId() {
		Ids currentids=Ids.findIdsByRowid(ids.getRandomValue());
		if (currentids==null) { // reached the end of initialized arrays, reinitialize
			initializeIds(this.ids);
			currentids=Ids.findIdsByRowid(ids.getRandomValue());
		}
		ids.setRandomValue(ids.getRandomValue()+1);
		int rno=START_RANDOM+currentids.getRandomValue();
		String id=ids.getHash()+String.valueOf(rno);
		logger.info("new id generated:"+id);
		return id;
	}

	private static String generateNewHash() {
		char[] buff=new char[2];
		buff[0]= (char)((new Random().nextInt(26))+65);
		buff[1]= (char)((new Random().nextInt(26))+65);
		return new String(buff);
	}
	
}
